﻿using System;
using System.Collections.Generic;
using System.Text;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.SystemUI;

namespace GISSystem.Class
{
    /// <summary>
    /// 这个类用于操作地图的一些控制
    /// 主要用于MapControl
    /// </summary>
    public class MapOperator
    {
        private IMap pMap;
        private IActiveView pActiveView;
        private IMapControl3 pMapControl;
        

        /// <summary>
        /// 获得mapControl的IMap对象，用于控制地图数据
        /// </summary>
        public IMap Map
        {
            get
            {
                return pMap;
            }
        }

        /// <summary>
        /// 获得MapControl的IActiveView对象，用与控制地图的显示等
        /// </summary>
        public IActiveView ActiveView
        {
            get
            {
                return pActiveView;
            }
        }

        /// <summary>
        /// 构造函数，暂时只能获得MapControl的IMap和IActiveView
        /// </summary>
        /// <param name="mapControl"></param>
        public MapOperator(AxMapControl mapControl)
        {
            pMap = mapControl.Map;
            pActiveView = mapControl.ActiveView;
            pMapControl = mapControl.Object as IMapControl3;
        }

        public void LoadMxd(string path)
        {
            if (pMapControl.CheckMxFile(path))
            {
                pMapControl.LoadMxFile(path,Type.Missing, Type.Missing);
                Update();
            }
            else
            {
                throw new Exception("文件格式错误。");
            }
        }

        /// <summary>
        /// 刷新，在MapControl的内容发生变化是执行，不然会有问题。。。
        /// </summary>
        private void Update()
        {
            pMap = pMapControl.Map;
            pActiveView = pMapControl.ActiveView;
        }

        #region 地图刷新系列
        /// <summary>
        /// 重绘整个地图，效率较低
        /// </summary>
        public void RefreshMap()
        {
            pActiveView.Refresh();
        }

        /// <summary>
        /// 刷新地图背景
        /// </summary>
        /// <param name="pEnv">可以为null，指定刷新范围</param>
        public void RefreshBackground(IEnvelope pEnv)
        {
            pActiveView.PartialRefresh(esriViewDrawPhase.esriViewBackground, null, pEnv);
        }

        /// <summary>
        /// 刷新地图前景
        /// </summary>
        /// <param name="pEnv"></param>
        public void RefreshForeground(IEnvelope pEnv)
        {
            pActiveView.PartialRefresh(esriViewDrawPhase.esriViewForeground, null, pEnv);
        }

        /// <summary>
        /// 刷新地理数据图像
        /// </summary>
        /// <param name="pEnv">可以为null，指定刷新范围</param>
        public void RefreshGeography(IEnvelope pEnv)
        {
            pActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeography, null, pEnv);
        }

        /// <summary>
        /// 刷新选择要素
        /// </summary>
        /// <param name="pEnv">可以为null，指定刷新范围</param>
        public void RefreshGeoSelection(IEnvelope pEnv)
        {
            pActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeoSelection, null, pEnv);
        }

        /// <summary>
        /// 刷新图形图层
        /// </summary>
        /// <param name="pEnv">可以为null，指定刷新范围</param>
        public void RefreshGraphics(IEnvelope pEnv)
        {
            pActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, pEnv);
        }

        /// <summary>
        /// 刷新选择的图形
        /// </summary>
        /// <param name="pEnv">可以为null，指定刷新范围</param>
        public void RefreshGraphicSelection(IEnvelope pEnv)
        {
            pActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphicSelection, null, pEnv);
        }
        #endregion

        #region 检测是否可以返回和前进
        /// <summary>
        /// 检测地图是否可以返回上一视图
        /// </summary>
        /// <returns></returns>
        public bool CanPrevExtent()
        {
            IExtentStack pExtentStack = pActiveView.ExtentStack;
            return pExtentStack.CanUndo();
        }

        /// <summary>
        /// 检测地图是否可以前进到下一视图
        /// </summary>
        /// <returns></returns>
        public bool CanNextExtent()
        {
            IExtentStack pExtentStack = pActiveView.ExtentStack;
            return pExtentStack.CanRedo();
        }
        #endregion

        #region 设置MapControl的工具(AE中自带)
        /// <summary>
        /// 清空MapControl的当前工具
        /// </summary>
        public void SetToolNull()
        {
            pMapControl.CurrentTool = null;
        }

        /// <summary>
        /// 设置工具到MapControl
        /// </summary>
        /// <param name="pCmd">工具命令</param>
        private void SetMapTools(ICommand pCmd)
        {
            pCmd.OnCreate(pMapControl);
            pMapControl.CurrentTool = pCmd as ITool;
        }

        /// <summary>
        /// 设置MapControl的当前工具为Pan-移动地图
        /// </summary>
        public void SetToolMapPan()
        {
            ICommand pPanTool = new ControlsMapPanToolClass();
            SetMapTools(pPanTool);
        }

        /// <summary>
        /// 设置MapControl的当前工具为ZoomIn-放大
        /// </summary>
        public void SetToolMapZoomIn()
        {
            ICommand pCmd = new ControlsMapZoomInToolClass();
            SetMapTools(pCmd);
        }

        /// <summary>
        /// 设置MapControl的当前工具为ZoomOut-缩小
        /// </summary>
        public void SetToolMapZoomOut()
        {
            ICommand pCmd = new ControlsMapZoomOutToolClass();
            SetMapTools(pCmd);
        }

        /// <summary>
        /// 设置MapControl的当前工具为选择要素
        /// </summary>
        public void SetToolSelectFeatures()
        {
            ICommand pCmd = new ControlsSelectFeaturesToolClass();
            SetMapTools(pCmd);
        }

        /// <summary>
        /// 设置MapControl的当前工具为Measure-测量图上距离
        /// </summary>
        public void SetToolMapMeasure()
        {
            ICommand pCmd = new ControlsMapMeasureToolClass();
            SetMapTools(pCmd);
        }

        /// <summary>
        /// 设置MapControl的当前工具为Identify-得到点击处的信息
        /// </summary>
        public void SetToolMapIdentify()
        {
            ICommand pCmd = new ControlsMapIdentifyToolClass();
            SetMapTools(pCmd);
        }
        #endregion

        #region 执行AE自带的命令
        /// <summary>
        /// 执行指定针对MapControl的命令
        /// </summary>
        /// <param name="pCmd"></param>
        private void CallCommand(ICommand pCmd)
        {
            pCmd.OnCreate(pMapControl);
            pCmd.OnClick();
        }

        /// <summary>
        /// 固定比例放大地图
        /// </summary>
        public void FixedZoomIn()
        {
            ICommand pCmd = new ControlsMapZoomInFixedCommandClass();
            CallCommand(pCmd);
        }

        /// <summary>
        /// 固定比例缩小地图
        /// </summary>
        public void FixedZoomOut()
        {
            ICommand pCmd = new ControlsMapZoomOutFixedCommandClass();
            CallCommand(pCmd);
        }

        /// <summary>
        /// 显示整幅地图
        /// </summary>
        public void FullExtent()
        {
            ICommand pCmd = new ControlsMapFullExtentCommandClass();
            CallCommand(pCmd);
        }

        /// <summary>
        /// 回到上一个视图
        /// </summary>
        public void PrevExtent()
        {
            ICommand pCmd = new ControlsMapZoomToLastExtentBackCommandClass();
            CallCommand(pCmd);
        }

        /// <summary>
        /// 前进到下一个视图
        /// </summary>
        public void NextExtent()
        {
            ICommand pCmd = new ControlsMapZoomToLastExtentForwardCommandClass();
            CallCommand(pCmd);
        }
        #endregion

        #region 寻找图层
        /// <summary>
        /// 获得指定名字的图层
        /// </summary>
        /// <param name="name">图层名称</param>
        /// <returns>图层</returns>
        public ILayer GetLayerByName(string name)
        {
            ILayer pLayer = null;

            for (int i = 0; i < pMap.LayerCount; i++)
            {
                ILayer pTempLayer = pMap.get_Layer(i);

                if (pTempLayer.Name == name)
                {
                    return pTempLayer;
                }
                //如果是组合图层，则在内部寻找
                if ((pTempLayer is ICompositeLayer) && (FindInGroupLayer((ICompositeLayer)pTempLayer, ref pLayer, name)))
                {
                    return pLayer;
                }
            }

            return null;
        }

        /// <summary>
        /// 在组图层中寻找图层
        /// </summary>
        /// <param name="pComLayer"></param>
        /// <param name="pLayer"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        private bool FindInGroupLayer(ICompositeLayer pComLayer, ref ILayer pLayer, string name)
        {
            for (int i = 0; i < pComLayer.Count; i++)
            {
                ILayer temp = pComLayer.get_Layer(i);

                if (temp.Name == name)
                {
                    pLayer = temp;
                    return true;
                }
                else if (temp is ICompositeLayer)
                {
                    if (FindInGroupLayer((ICompositeLayer)temp, ref pLayer, name))
                    {
                        return true;
                    }
                }
            }

            return false;
        }
        #endregion
    }
}
